package main

import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"github.com/go-sql-driver/mysql"
	"log"
	"math"
	"math/rand"
	"net/http"
	"os"
	"strconv"
	"sync"
	"sync/atomic"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis/v8"
	_ "github.com/go-sql-driver/mysql"
)

// 删除硬编码的配置常量
var (
	MysqlDSN      string
	RedisAddr     string
	RedisPassword string
	RedisDB       int
)

// 初始化配置（在 main 函数开头调用）
func initConfig() {
	// 从环境变量读取配置，设置默认值
	MysqlDSN = os.Getenv("MYSQL_DSN")
	if MysqlDSN == "" {
		MysqlDSN = "root:123456@tcp(localhost:3306)/go_redis?parseTime=true" // 本地开发默认值
	}

	RedisAddr = os.Getenv("REDIS_ADDR")
	if RedisAddr == "" {
		RedisAddr = "localhost:6379" // 本地开发默认值
	}

	RedisPassword = os.Getenv("REDIS_PASSWORD")

	// 处理 Redis DB
	dbStr := os.Getenv("REDIS_DB")
	if dbStr == "" {
		dbStr = "0"
	}
	RedisDB, _ = strconv.Atoi(dbStr)
}

// 全局变量
var (
	rdb *redis.Client
	db  *sql.DB
)

// 监控指标
var (
	redisHits       uint64 // Redis缓存命中次数
	redisMisses     uint64 // Redis缓存未命中次数
	dbQueryCount    uint64 // 数据库查询次数
	dbErrorCount    uint64 // 数据库错误次数
	redisErrorCount uint64 // Redis错误次数
	slowQueryCount  uint64 // 慢查询次数（>100ms）

	// 新增指标
	totalRequests         uint64         // 总请求数
	totalResponses        uint64         // 总响应数
	requestCounter        uint64         // 计数器，用于计算QPS
	responseCounter       uint64         // 计数器，用于计算QPS
	totalResponseTime     int64          // 总响应时间(微秒)
	requestPerEndpoint    sync.Map       // 每个端点的请求计数
	responseTimePerMethod sync.Map       // 每种HTTP方法的响应时间
	statusCodeCounter     sync.Map       // HTTP状态码计数
	userAgentCounter      sync.Map       // 用户代理计数
	responseTimeBuckets   [6]uint64      // 响应时间分布(0-10ms, 10-50ms, 50-100ms, 100-500ms, 500-1000ms, >1000ms)
	concurrentRequests    int64          // 当前并发请求数
	maxConcurrentRequests int64          // 最大并发请求数
	lastMinuteRequests    *RingBuffer    // 最近一分钟的请求数
	lastMinuteResponses   *RingBuffer    // 最近一分钟的响应数
	requestSizeTotal      uint64         // 总请求大小(字节)
	responseSizeTotal     uint64         // 总响应大小(字节)
	startTime             time.Time      // 启动时间
	lastResetTime         time.Time      // 最后重置计数器时间
	rateLimiterCounter    map[string]int // 简易速率限制计数器
	rateLimiterMutex      sync.Mutex     // 速率限制锁
)

// RingBuffer 定义环形缓冲区
type RingBuffer struct {
	values  []uint64
	pos     int
	size    int
	sum     uint64
	counter uint64
	mu      sync.Mutex
}

// NewRingBuffer 创建一个新的环形缓冲区
func NewRingBuffer(size int) *RingBuffer {
	return &RingBuffer{
		values: make([]uint64, size),
		size:   size,
		pos:    0,
	}
}

// Add 向环形缓冲区添加值
func (r *RingBuffer) Add(val uint64) {
	r.mu.Lock()
	defer r.mu.Unlock()

	r.sum = r.sum - r.values[r.pos] + val
	r.values[r.pos] = val
	r.pos = (r.pos + 1) % r.size
	r.counter++
}

// Sum 获取环形缓冲区所有值的总和
func (r *RingBuffer) Sum() uint64 {
	r.mu.Lock()
	defer r.mu.Unlock()
	return r.sum
}

// Avg 获取环形缓冲区所有值的平均值
func (r *RingBuffer) Avg() float64 {
	r.mu.Lock()
	defer r.mu.Unlock()

	filled := r.size
	if r.counter < uint64(r.size) {
		filled = int(r.counter)
	}

	if filled == 0 {
		return 0
	}

	return float64(r.sum) / float64(filled)
}

// 用户模型
type User struct {
	ID    int    `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

// EnhancedMetrics 扩展的监控指标结构
type EnhancedMetrics struct {
	// 基础状态
	RedisStatus     string  `json:"redis_status"`      // Redis连接状态
	MySQLStatus     string  `json:"mysql_status"`      // MySQL连接状态
	CacheHitRate    float64 `json:"cache_hit_rate"`    // 缓存命中率
	DbActiveConns   int     `json:"db_active_conns"`   // 活跃数据库连接数
	DbIdleConns     int     `json:"db_idle_conns"`     // 空闲数据库连接数
	DbQueryCount    uint64  `json:"db_query_count"`    // 数据库查询总数
	DbErrorCount    uint64  `json:"db_error_count"`    // 数据库错误总数
	RedisErrorCount uint64  `json:"redis_error_count"` // Redis错误总数
	SlowQueryCount  uint64  `json:"slow_query_count"`  // 慢查询次数
	Uptime          string  `json:"uptime"`            // 服务运行时间

	// 请求统计
	TotalRequests      uint64             `json:"total_requests"`       // 总请求数
	TotalResponses     uint64             `json:"total_responses"`      // 总响应数
	RequestsPerSecond  float64            `json:"requests_per_second"`  // 每秒请求数
	ResponsesPerSecond float64            `json:"responses_per_second"` // 每秒响应数
	AvgResponseTime    float64            `json:"avg_response_time"`    // 平均响应时间(毫秒)
	EndpointStats      map[string]uint64  `json:"endpoint_stats"`       // 端点请求统计
	StatusCodeStats    map[string]uint64  `json:"status_code_stats"`    // 状态码统计
	MethodStats        map[string]float64 `json:"method_stats"`         // HTTP方法响应时间

	// 资源使用
	ConcurrentRequests    int64     `json:"concurrent_requests"`     // 当前并发请求数
	MaxConcurrentRequests int64     `json:"max_concurrent_requests"` // 最大并发请求数
	AvgRequestSize        float64   `json:"avg_request_size"`        // 平均请求大小(字节)
	AvgResponseSize       float64   `json:"avg_response_size"`       // 平均响应大小(字节)
	LastMinuteQPS         float64   `json:"last_minute_qps"`         // 最近一分钟QPS
	ResponseTimeBuckets   [6]uint64 `json:"response_time_buckets"`   // 响应时间分布

	// 容量和限制
	DbMaxOpenConns    int `json:"db_max_open_conns"`    // 数据库最大打开连接数
	DbMaxIdleConns    int `json:"db_max_idle_conns"`    // 数据库最大空闲连接数
	RedisPoolSize     int `json:"redis_pool_size"`      // Redis连接池大小
	RedisMinIdleConns int `json:"redis_min_idle_conns"` // Redis最小空闲连接数
}

// 响应时间桶边界（毫秒）
var responseTimeBoundaries = []int{10, 50, 100, 500, 1000}

func main() {
	initConfig()

	// 初始化监控数据结构
	initMonitoring()

	// 初始化连接
	setupRedis()
	setupMySQL()

	// 创建Gin路由
	r := gin.Default()

	// 添加请求监控中间件
	r.Use(monitoringMiddleware())

	// 路由配置
	r.GET("/user/:id", getUserHandler)
	r.GET("/metrics", metricsHandler) // 监控API端点
	r.GET("/health", healthCheckHandler)

	r.POST("/stress/start", startStressTestHandler)
	r.POST("/stress/stop", stopStressTestHandler)
	r.GET("/stress/status", stressTestStatusHandler)
	r.GET("/stress/result", stressTestResultHandler)
	// 静态文件服务
	r.StaticFile("/", "./static/index.html") // 仪表盘首页
	r.Static("/static", "./static")          // 静态资源目录

	// 启动定期任务
	go startPeriodicTasks()

	// 启动服务器
	if err := r.Run(":8080"); err != nil {
		log.Fatal("Failed to start server:", err)
	}
}

// 初始化监控数据结构
func initMonitoring() {
	startTime = time.Now()
	lastResetTime = time.Now()
	lastMinuteRequests = NewRingBuffer(60)    // 一分钟60个槽位，每秒一个
	lastMinuteResponses = NewRingBuffer(60)   // 一分钟60个槽位，每秒一个
	rateLimiterCounter = make(map[string]int) // 初始化速率限制器

	// 初始化每秒统计数据
	for i := 0; i < 60; i++ {
		lastMinuteRequests.Add(0)
		lastMinuteResponses.Add(0)
	}
}

// 定期任务
func startPeriodicTasks() {
	// 每秒执行的任务
	secondTicker := time.NewTicker(1 * time.Second)
	go func() {
		for range secondTicker.C {
			// 计算并重置每秒请求和响应计数
			reqCount := atomic.SwapUint64(&requestCounter, 0)
			respCount := atomic.SwapUint64(&responseCounter, 0)

			// 存储到滑动窗口中
			lastMinuteRequests.Add(reqCount)
			lastMinuteResponses.Add(respCount)
		}
	}()

	// 每分钟执行的任务
	minuteTicker := time.NewTicker(1 * time.Minute)
	go func() {
		for range minuteTicker.C {
			// 清理速率限制器
			rateLimiterMutex.Lock()
			rateLimiterCounter = make(map[string]int)
			rateLimiterMutex.Unlock()
		}
	}()
}

// 请求监控中间件
func monitoringMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 增加总请求计数
		atomic.AddUint64(&totalRequests, 1)
		atomic.AddUint64(&requestCounter, 1)

		// 更新端点统计
		endpoint := c.FullPath()
		if endpoint == "" {
			endpoint = "unknown"
		}
		val, _ := requestPerEndpoint.LoadOrStore(endpoint, uint64(0))
		requestPerEndpoint.Store(endpoint, val.(uint64)+1)

		// 记录请求大小
		reqSize := c.Request.ContentLength
		if reqSize > 0 {
			atomic.AddUint64(&requestSizeTotal, uint64(reqSize))
		}

		// 增加并发请求计数
		currentConcurrent := atomic.AddInt64(&concurrentRequests, 1)

		// 更新最大并发请求数
		for {
			maxConcurrent := atomic.LoadInt64(&maxConcurrentRequests)
			if currentConcurrent <= maxConcurrent {
				break
			}
			if atomic.CompareAndSwapInt64(&maxConcurrentRequests, maxConcurrent, currentConcurrent) {
				break
			}
		}

		// 记录请求开始时间
		startTime := time.Now()

		// 创建自定义ResponseWriter，用于捕获状态码和响应大小
		responseWriter := &responseWriterMonitor{ResponseWriter: c.Writer}
		c.Writer = responseWriter

		// 处理请求
		c.Next()

		// 记录响应结束时间
		elapsed := time.Since(startTime)
		elapsedMicros := elapsed.Microseconds()

		// 更新总响应时间
		atomic.AddInt64(&totalResponseTime, elapsedMicros)

		// 增加总响应计数
		atomic.AddUint64(&totalResponses, 1)
		atomic.AddUint64(&responseCounter, 1)

		// 更新HTTP方法响应时间统计
		method := c.Request.Method
		val, _ = responseTimePerMethod.LoadOrStore(method, int64(0))
		total := val.(int64) + elapsedMicros
		responseTimePerMethod.Store(method, total)

		// 更新状态码统计
		statusCode := fmt.Sprintf("%d", responseWriter.status)
		val, _ = statusCodeCounter.LoadOrStore(statusCode, uint64(0))
		statusCodeCounter.Store(statusCode, val.(uint64)+1)

		// 更新用户代理统计
		userAgent := c.Request.UserAgent()
		if userAgent != "" {
			val, _ = userAgentCounter.LoadOrStore(userAgent, uint64(0))
			userAgentCounter.Store(userAgent, val.(uint64)+1)
		}

		// 更新响应时间分布
		elapsedMs := int(elapsed.Milliseconds())
		bucketIndex := 5 // 默认最后一个桶 (>1000ms)
		for i, boundary := range responseTimeBoundaries {
			if elapsedMs < boundary {
				bucketIndex = i
				break
			}
		}
		atomic.AddUint64(&responseTimeBuckets[bucketIndex], 1)

		// 记录响应大小
		if responseWriter.size > 0 {
			atomic.AddUint64(&responseSizeTotal, uint64(responseWriter.size))
		}

		// 减少并发请求计数
		atomic.AddInt64(&concurrentRequests, -1)
	}
}

// responseWriterMonitor 用于监控响应
type responseWriterMonitor struct {
	gin.ResponseWriter
	status int
	size   int
}

// WriteHeader 重写WriteHeader方法以捕获状态码
func (w *responseWriterMonitor) WriteHeader(code int) {
	w.status = code
	w.ResponseWriter.WriteHeader(code)
}

// Write 重写Write方法以捕获响应大小
func (w *responseWriterMonitor) Write(b []byte) (int, error) {
	size, err := w.ResponseWriter.Write(b)
	w.size += size
	return size, err
}

// Status 获取状态码
func (w *responseWriterMonitor) Status() int {
	if w.status == 0 {
		return http.StatusOK
	}
	return w.status
}

// Size 获取响应大小
func (w *responseWriterMonitor) Size() int {
	return w.size
}

// 初始化Redis连接
func setupRedis() {
	rdb = redis.NewClient(&redis.Options{
		Addr:         RedisAddr,
		Password:     RedisPassword,
		DB:           RedisDB,
		PoolSize:     100, // 连接池大小
		MinIdleConns: 10,  // 最小空闲连接数
	})

	// 添加重试逻辑
	maxRetries := 5
	for i := 0; i < maxRetries; i++ {
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		_, err := rdb.Ping(ctx).Result()
		cancel()

		if err == nil {
			log.Println("Redis连接成功")
			return
		}

		log.Printf("Redis连接失败，正在重试 (%d/%d)", i+1, maxRetries)
		time.Sleep(2 * time.Second)
	}

	log.Fatal("无法连接 Redis")
}

// 初始化MySQL连接
func setupMySQL() {
	var err error
	db, err = sql.Open("mysql", MysqlDSN)
	if err != nil {
		log.Fatal("Failed to connect to MySQL:", err)
	}

	// 配置连接池
	db.SetMaxOpenConns(100) // 最大打开连接数
	db.SetMaxIdleConns(20)  // 最大空闲连接数
	db.SetConnMaxLifetime(time.Hour)

	// 测试连接
	if err := db.Ping(); err != nil {
		log.Fatal("Failed to ping MySQL:", err)
	}

	log.Println("MySQL连接成功")
}

// 健康检查处理函数
func healthCheckHandler(c *gin.Context) {
	status := make(map[string]string)

	// 检查MySQL连接
	if err := db.Ping(); err != nil {
		status["mysql"] = "unhealthy"
	} else {
		status["mysql"] = "healthy"
	}

	// 检查Redis连接
	ctx := context.Background()
	if _, err := rdb.Ping(ctx).Result(); err != nil {
		status["redis"] = "unhealthy"
	} else {
		status["redis"] = "healthy"
	}

	// 确定总体健康状态
	overallStatus := http.StatusOK
	for _, v := range status {
		if v != "healthy" {
			overallStatus = http.StatusServiceUnavailable
			break
		}
	}

	c.JSON(overallStatus, gin.H{
		"status":    status,
		"timestamp": time.Now().Format(time.RFC3339),
	})
}

// 监控指标处理函数
func metricsHandler(c *gin.Context) {
	// 检查Redis连接
	redisStatus := "healthy"
	ctx := context.Background()
	if _, err := rdb.Ping(ctx).Result(); err != nil {
		redisStatus = "unhealthy"
	}

	// 检查MySQL连接
	mysqlStatus := "healthy"
	if err := db.Ping(); err != nil {
		mysqlStatus = "unhealthy"
	}

	// 计算缓存命中率
	hits := atomic.LoadUint64(&redisHits)
	misses := atomic.LoadUint64(&redisMisses)
	var hitRate float64 = 0
	if hits+misses > 0 {
		hitRate = float64(hits) / float64(hits+misses) * 100
	}

	// 获取MySQL连接池统计
	stats := db.Stats()

	// 计算平均响应时间(毫秒)
	totalResp := atomic.LoadUint64(&totalResponses)
	avgRespTime := 0.0
	if totalResp > 0 {
		avgRespTime = float64(atomic.LoadInt64(&totalResponseTime)) / float64(totalResp) / 1000.0
	}

	// 计算QPS
	now := time.Now()
	duration := now.Sub(lastResetTime).Seconds()
	if duration == 0 {
		duration = 1 // 防止除以零
	}
	requestsPerSecond := float64(atomic.LoadUint64(&totalRequests)) / duration
	responsesPerSecond := float64(atomic.LoadUint64(&totalResponses)) / duration

	// 计算最近一分钟的平均QPS
	lastMinuteQPS := lastMinuteRequests.Avg()

	// 计算平均请求和响应大小
	avgReqSize := 0.0
	totalReq := atomic.LoadUint64(&totalRequests)
	if totalReq > 0 {
		avgReqSize = float64(atomic.LoadUint64(&requestSizeTotal)) / float64(totalReq)
	}

	avgRespSize := 0.0
	if totalResp > 0 {
		avgRespSize = float64(atomic.LoadUint64(&responseSizeTotal)) / float64(totalResp)
	}

	// 获取端点统计
	endpointStats := make(map[string]uint64)
	requestPerEndpoint.Range(func(key, value interface{}) bool {
		endpointStats[key.(string)] = value.(uint64)
		return true
	})

	// 获取状态码统计
	statusCodeStats := make(map[string]uint64)
	statusCodeCounter.Range(func(key, value interface{}) bool {
		statusCodeStats[key.(string)] = value.(uint64)
		return true
	})

	// 获取HTTP方法响应时间
	methodStats := make(map[string]float64)
	responseTimePerMethod.Range(func(key, value interface{}) bool {
		method := key.(string)
		totalMicros := value.(int64)

		// 从端点统计中获取该方法的请求数
		val, ok := requestPerEndpoint.Load(method)
		if ok && val.(uint64) > 0 {
			// 计算平均响应时间(毫秒)
			methodStats[method] = float64(totalMicros) / float64(val.(uint64)) / 1000.0
		}
		return true
	})

	metrics := EnhancedMetrics{
		RedisStatus:     redisStatus,
		MySQLStatus:     mysqlStatus,
		CacheHitRate:    hitRate,
		DbActiveConns:   stats.InUse,
		DbIdleConns:     stats.Idle,
		DbQueryCount:    atomic.LoadUint64(&dbQueryCount),
		DbErrorCount:    atomic.LoadUint64(&dbErrorCount),
		RedisErrorCount: atomic.LoadUint64(&redisErrorCount),
		SlowQueryCount:  atomic.LoadUint64(&slowQueryCount),
		Uptime:          time.Since(startTime).String(),

		TotalRequests:      totalReq,
		TotalResponses:     totalResp,
		RequestsPerSecond:  math.Round(requestsPerSecond*100) / 100,
		ResponsesPerSecond: math.Round(responsesPerSecond*100) / 100,
		AvgResponseTime:    math.Round(avgRespTime*100) / 100,
		EndpointStats:      endpointStats,
		StatusCodeStats:    statusCodeStats,
		MethodStats:        methodStats,

		ConcurrentRequests:    atomic.LoadInt64(&concurrentRequests),
		MaxConcurrentRequests: atomic.LoadInt64(&maxConcurrentRequests),
		AvgRequestSize:        math.Round(avgReqSize*100) / 100,
		AvgResponseSize:       math.Round(avgRespSize*100) / 100,
		LastMinuteQPS:         math.Round(lastMinuteQPS*100) / 100,
		ResponseTimeBuckets:   responseTimeBuckets,

		DbMaxOpenConns:    stats.MaxOpenConnections,
		DbMaxIdleConns:    20,  // 从setupMySQL中获取
		RedisPoolSize:     100, // 从setupRedis中获取
		RedisMinIdleConns: 10,  // 从setupRedis中获取
	}

	c.JSON(http.StatusOK, metrics)
}

// 用户信息处理函数
func getUserHandler(c *gin.Context) {
	id := c.Param("id")

	// 记录开始时间用于计算性能
	start := time.Now()

	//优先从Redis获取
	user, err := getUserFromCache(id)
	if err == nil {
		// 缓存命中
		atomic.AddUint64(&redisHits, 1)
		c.JSON(http.StatusOK, user)
		return
	}

	// 缓存未命中
	atomic.AddUint64(&redisMisses, 1)

	// 查询数据库
	atomic.AddUint64(&dbQueryCount, 1)
	user, err = getUserFromDB(id)

	// 计算查询耗时，记录慢查询
	elapsed := time.Since(start)
	if elapsed > 100*time.Millisecond {
		atomic.AddUint64(&slowQueryCount, 1)
		log.Printf("慢查询警告: 获取用户ID=%s 耗时: %v", id, elapsed)
	}

	if err != nil {
		atomic.AddUint64(&dbErrorCount, 1)
		if err == sql.ErrNoRows {
			c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// 将结果写入Redis（异步）
	go setUserToCache(user)

	c.JSON(http.StatusOK, user)
}

// 从Redis获取用户信息
func getUserFromCache(userID string) (*User, error) {
	ctx := context.Background()
	key := fmt.Sprintf("user:%s", userID)

	start := time.Now()
	data, err := rdb.Get(ctx, key).Result()

	// 记录Redis操作耗时
	elapsed := time.Since(start)
	if elapsed > 50*time.Millisecond {
		log.Printf("Redis慢操作警告: 获取用户ID=%s 耗时: %v", userID, elapsed)
	}

	if err != nil {
		if err != redis.Nil {
			// 只有真正的错误才计数，缓存未命中不算错误
			atomic.AddUint64(&redisErrorCount, 1)
			log.Printf("Redis错误: %v", err)
		}
		return nil, err
	}

	var user User
	if err := json.Unmarshal([]byte(data), &user); err != nil {
		return nil, err
	}

	return &user, nil
}

// 将用户信息存入Redis
func setUserToCache(user *User) error {
	ctx := context.Background()
	key := fmt.Sprintf("user:%d", user.ID)

	data, err := json.Marshal(user)
	if err != nil {
		return err
	}

	start := time.Now()
	// 设置缓存过期时间（30分钟）
	err = rdb.Set(ctx, key, data, 30*time.Minute).Err()

	// 记录Redis操作耗时
	elapsed := time.Since(start)
	if elapsed > 50*time.Millisecond {
		log.Printf("Redis慢操作警告: 缓存用户ID=%d 耗时: %v", user.ID, elapsed)
	}

	if err != nil {
		atomic.AddUint64(&redisErrorCount, 1)
		log.Printf("Redis缓存错误: %v", err)
	}

	return err
}

// 从数据库获取用户信息
func getUserFromDB(userID string) (*User, error) {
	query := `SELECT id, name, email FROM users WHERE id = ?`

	switch rand.Intn(100) {
	case 0: // 1%概率触发锁等待超时
		time.Sleep(1500 * time.Millisecond)
		return nil, &mysql.MySQLError{Number: 1205, Message: "Lock wait timeout"}
	case 1, 2: // 2%概率触发高负载延迟
		time.Sleep(time.Duration(300+rand.Intn(700)) * time.Millisecond) // 300-1000ms
	default: // 正常情况
		base := 15 + rand.Intn(25) // 15-40ms基础延迟
		time.Sleep(time.Duration(base) * time.Millisecond)
	}

	start := time.Now()
	row := db.QueryRow(query, userID)

	var user User
	err := row.Scan(&user.ID, &user.Name, &user.Email)

	// 记录数据库操作耗时
	elapsed := time.Since(start)
	if elapsed > 100*time.Millisecond {
		log.Printf("MySQL慢查询: 获取用户ID=%s 耗时: %v", userID, elapsed)
	}

	if err != nil {
		if err != sql.ErrNoRows {
			log.Printf("数据库查询错误: %v", err)
		}
		return nil, err
	}

	return &user, nil
}

// 压力测试配置
type StressTestConfig struct {
	Duration    int    `json:"duration"`    // 测试持续时间(秒)
	Concurrency int    `json:"concurrency"` // 并发数
	Endpoint    string `json:"endpoint"`    // 测试端点
}

// 压力测试结果
type StressTestResult struct {
	TotalRequests   int64         `json:"total_requests"`
	SuccessCount    int64         `json:"success_count"`
	ErrorCount      int64         `json:"error_count"`
	AvgResponseTime float64       `json:"avg_response_time"`
	RequestsPerSec  float64       `json:"requests_per_sec"`
	MinResponseTime float64       `json:"min_response_time"`
	MaxResponseTime float64       `json:"max_response_time"`
	StatusCodeDist  map[int]int64 `json:"status_code_dist"`
}

// 全局压力测试控制
var (
	stressTestRunning bool
	stressTestCancel  context.CancelFunc
	stressTestMutex   sync.Mutex
)

// 启动压力测试
func startStressTestHandler(c *gin.Context) {
	stressTestMutex.Lock()
	defer stressTestMutex.Unlock()

	if stressTestRunning {
		c.JSON(http.StatusBadRequest, gin.H{"error": "压力测试已在运行"})
		return
	}

	var config StressTestConfig
	if err := c.ShouldBindJSON(&config); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 验证参数
	if config.Duration <= 0 || config.Duration > 600 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "持续时间应在1-600秒之间"})
		return
	}
	if config.Concurrency <= 0 || config.Concurrency > 1000 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "并发数应在1-1000之间"})
		return
	}

	ctx, cancel := context.WithCancel(context.Background())
	stressTestCancel = cancel
	stressTestRunning = true

	// 启动压力测试协程
	go runStressTest(ctx, config)

	c.JSON(http.StatusOK, gin.H{"message": "压力测试已启动"})
}

// 停止压力测试
func stopStressTestHandler(c *gin.Context) {
	stressTestMutex.Lock()
	defer stressTestMutex.Unlock()

	if !stressTestRunning {
		c.JSON(http.StatusBadRequest, gin.H{"error": "没有正在运行的压力测试"})
		return
	}

	stressTestCancel()
	stressTestRunning = false

	c.JSON(http.StatusOK, gin.H{"message": "压力测试已停止"})
}

// 压力测试状态
func stressTestStatusHandler(c *gin.Context) {
	stressTestMutex.Lock()
	running := stressTestRunning
	stressTestMutex.Unlock()

	c.JSON(http.StatusOK, gin.H{"running": running})
}

// 新增获取测试结果的接口
func stressTestResultHandler(c *gin.Context) {
	stressTestResultMu.RLock()
	defer stressTestResultMu.RUnlock()

	if stressTestResult == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "暂无压力测试结果"})
		return
	}

	c.JSON(http.StatusOK, stressTestResult)
}

// 实际执行压力测试
func runStressTest(ctx context.Context, config StressTestConfig) {
	defer func() {
		stressTestMutex.Lock()
		stressTestRunning = false
		stressTestMutex.Unlock()
	}()

	var (
		wg            sync.WaitGroup
		totalRequests int64
		successCount  int64
		errorCount    int64
		totalTime     int64
		minTime       = int64(math.MaxInt64)
		maxTime       = int64(0)
		statusCodes   = make(map[int]int64)
		statusMutex   sync.Mutex
	)

	client := &http.Client{
		Timeout: 10 * time.Second,
	}

	endpoint := config.Endpoint
	if endpoint == "" {
		endpoint = "/user/1" // 默认测试用户查询接口
	}

	// 创建请求URL
	reqURL := "http://localhost:8080" + endpoint

	// 设置超时
	ctx, cancel := context.WithTimeout(ctx, time.Duration(config.Duration)*time.Second)
	defer cancel()

	// 启动worker
	startTime := time.Now()
	for i := 0; i < config.Concurrency; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for {
				select {
				case <-ctx.Done():
					return
				default:
					// 执行请求
					reqStart := time.Now()
					resp, err := client.Get(reqURL)
					elapsed := time.Since(reqStart).Milliseconds()

					atomic.AddInt64(&totalRequests, 1)
					atomic.AddInt64(&totalTime, elapsed)

					// 更新最小/最大响应时间
					if elapsed < atomic.LoadInt64(&minTime) {
						atomic.StoreInt64(&minTime, elapsed)
					}
					if elapsed > atomic.LoadInt64(&maxTime) {
						atomic.StoreInt64(&maxTime, elapsed)
					}

					if err != nil {
						atomic.AddInt64(&errorCount, 1)
						continue
					}

					// 记录状态码
					statusMutex.Lock()
					statusCodes[resp.StatusCode]++
					statusMutex.Unlock()
					resp.Body.Close()

					if resp.StatusCode < 400 {
						atomic.AddInt64(&successCount, 1)
					} else {
						atomic.AddInt64(&errorCount, 1)
					}
				}
			}
		}()
	}

	// 等待测试完成
	wg.Wait()
	testDuration := time.Since(startTime).Seconds()

	// 准备结果
	result := StressTestResult{
		TotalRequests:  totalRequests,
		SuccessCount:   successCount,
		ErrorCount:     errorCount,
		RequestsPerSec: float64(totalRequests) / testDuration,
		StatusCodeDist: statusCodes,
	}

	if totalRequests > 0 {
		result.AvgResponseTime = float64(totalTime) / float64(totalRequests)
		result.MinResponseTime = float64(minTime)
		result.MaxResponseTime = float64(maxTime)
	}

	// 加锁保存结果
	stressTestResultMu.Lock()
	stressTestResult = &result
	stressTestResultMu.Unlock()

	// 这里可以存储或输出结果
	log.Printf("压力测试完成: %+v", result)
}

var (
	stressTestResult   *StressTestResult
	stressTestResultMu sync.RWMutex
)
